package com.canbot.u05.control;

import com.alibaba.fastjson.JSON;
import com.canbot.u05.api.MsgCon;
import com.canbot.u05.api.ReceiveDataInterface;
import com.canbot.u05.socket.StringMsgBean;
import com.canbot.u05.utils.Logger;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;

/**
 * 通过socket和fpga通信
 *
 * @author Administrator
 */
public class SocketClient {

        private static final String TAG = "SocketClient";

        private volatile boolean flag = true;

        private DataInputStream mDataInputStream;

        private OutputStream mOutputSteamFpga = null;

        // private SendMsgThread sendMsgThread = null;

        private ReceiveDataInterface mInterface;

        private byte[] mLastSendMsg = null; // 最后一次发送失败的消息

        private ISendLisenter iSendLisenter = null;

        public SocketClient() {

        }

        public void init(ReceiveDataInterface listener) {
                this.mInterface = listener;
        }

        /**
         * true 表示连接socket 成功，false则是失败
         */
        private boolean success = false;

        /**
         * 返回 true 表示连接socket 成功，false则是失败.
         *
         * @return
         */
        public boolean connectToServer(final Runnable runnable) {
                Thread thread = new Thread() {
                        public void run() {
                                Logger.e(TAG, "SocketThread will be running!");
                                Socket socket = null;
                                try {
                                        socket = new Socket("192.168.12.12", 2810);
                                        Logger.e(TAG, "socekt connect success:" + socket.getInetAddress());
                                        mOutputSteamFpga = socket.getOutputStream();
                                        mDataInputStream = new DataInputStream(socket.getInputStream());
                                        success = true;
                                        if (runnable != null) {
                                                runnable.run();
                                        }
                                }
                                catch (UnknownHostException e) {
                                        e.printStackTrace();
                                        Logger.e(TAG, "UnknownHostException :" + e.toString());
//                        throw  new  RuntimeException(e);
                                        success = false;
                                }
                                catch (IOException e) {
                                        e.printStackTrace();
                                        Logger.e(TAG, "IOException :" + e.toString());
//                        throw  new  RuntimeException(e);
                                        success = false;
                                }
                        }
                };
                thread.start();
                try {
                        thread.join();
                }
                catch (InterruptedException e) {
                        e.printStackTrace();
                        return false;
                }
                return success;
        }


        /**
         * 开始处理输入和输出
         */
        public void startProcess() {
                new Thread() {
                        @Override
                        public void run() {
                                while (flag) {
                                        decodeData(mDataInputStream);
                                }
                        }
                }.start();
        }


        /**
         * 目前在手持端没有对接收到的数据进行处理。
         * 人脸追踪发给GPU的数据同样也会在这里收到，注意只有msgType，没有msgData。
         * 可以看头部的具体协议.
         * 不能删除.
         *
         * @param is
         */
        private void decodeData(DataInputStream is) {
                try {
                        byte DH_Head = is.readByte();
//                        Logger.e(TAG,"DH_Head===="+DH_Head);

                        if (DH_Head == Cmd.Head_H) {
                                byte DL_Head = is.readByte();
//                                Logger.e(TAG,"DL_Head222===="+DL_Head);
                                if (Cmd.Head_L == DL_Head) {
                                        byte d = is.readByte();
                                        byte c = is.readByte();
                                        byte e = is.readByte();
                                        byte f = is.readByte();
                                        int len = (f * 256) + (e & 0xff);
//                                        Logger.e(TAG,"len===="+len);
                                        if (len > 0) { // 有时候读取到的数据为负数
                                                byte[] data = new byte[len + 1];
                                                is.readFully(data);
                                                Logger.e(TAG,"data===="+ Arrays.toString(data));
                                                if (checkData(data)) {
                                                        byte cmd = data[0];
//                                                        Logger.e(TAG,"cmd  ===="+cmd);
                                                        decodeTouChuanData2(len + 1, data);
                                                }
                                        }
                                }
                        }

                }
                catch (IOException e) {
                        flag = false;
                        e.printStackTrace();
                        Logger.d(TAG, "IOException=" + e.toString());
                }
        }

        /**
         * GuideActivity GuideMapAddTaskActivity 等导览任务相关界面接受胸口地图保存、加载结果
         * 方法名 onMapEvent(StringMsgBean bean)
         * <p>
         * EventBus.getDefault().post(stringMsgBean);
         *
         * @param len
         * @param data
         */
        private void decodeTouChuanData2(int len, byte[] data) {
                if (len - 4 <= 0) {
                        Logger.e(TAG, "数据有误.");
                        return;
                }
                byte[] content = new byte[len - 4];
                int msgType = (data[2] * 256) + (data[3] & 0xff);
                Logger.d(TAG, "胸口msgType" + msgType);
                System.arraycopy(data, 4, content, 0, len - 4);
                String temp = new String(content);
                Logger.e(TAG, "receiverData====" + temp + "    =msgType=" + msgType);
                StringMsgBean stringMsgBean = new StringMsgBean(msgType, temp);
                mInterface.onReceive(JSON.toJSONString(stringMsgBean));

        }

        private boolean checkData(byte[] data) {
                int length = data.length;
                if (data[length - 2] == MsgCon.protocol_Tail_H && data[length - 1] == MsgCon.protocol_Tail_L) {
                        int datalen = length - 3;
                        byte sum = 0;
                        for (int i = 0; i < datalen; i++) {
                                sum += data[i];
                        }
                        if (sum == data[length - 3]) {
                                return true;
                        }
                }
                return true;
        }


        /**
         * 发送消息
         */
        public void sendMessage(final byte[] data) {
                Logger.e(TAG, "sendStringMsgToServer  start msg: ");
                if (mOutputSteamFpga != null) {
                        try {
                                mOutputSteamFpga.write(data);
                                mOutputSteamFpga.flush();
                                Logger.d(TAG, "write  success===" + Arrays.toString(data));
                                return;
                        }
                        catch (IOException e) {
                                e.printStackTrace();
                                Logger.d(TAG, "write IOException " + e.getLocalizedMessage());
                                connectToServer(new Runnable() {
                                        @Override
                                        public void run() {
                                                sendMessage(data);

                                        }
                                });
                        }
                }
                else {
                    Logger.e(TAG, "write  mFileOutputStream is  null");
                    connectToServer(new Runnable() {
                        @Override
                        public void run() {
                            sendMessage(data);

                        }
                    });
                }
        }
}
